package br.com.nuccitec.jfera.basic;

import java.util.List;

import br.com.nuccitec.jfera.api.MessageResponse;
import br.com.nuccitec.jfera.api.IBusinessExecutor;
import br.com.nuccitec.jfera.api.IExecutorMapsManager;
import br.com.nuccitec.jfera.api.IRemoteResponse;
import br.com.nuccitec.jfera.api.IRequestHandler;
import br.com.nuccitec.jfera.api.NoExecutorFoundException;
import br.com.nuccitec.jfera.api.RemoteRequest;
import br.com.nuccitec.jfera.collaborator.CollaboratorFacade;
import br.com.nuccitec.jfera.security.ISecurityExecutor;

public class RequestHandler implements IRequestHandler {
	private IExecutorMapsManager mapsManager;
	private CollaboratorFacade colaboratorFacade;

	@Override
	public IRemoteResponse executeRequest(RemoteRequest request) throws NoExecutorFoundException {
		IRemoteResponse response = executeSecurity(request, mapsManager.getGeneralSecurityExecutors(request.getId()));
		if (response != null) {
			return response;
		}
		response = executeSecurity(request, mapsManager.getSpecificSecurityExecutors(request.getId()));
		if (response != null) {
			return response;
		}
		IBusinessExecutor bExecutor = mapsManager.getBusinessExecutor(request.getId());
		if (bExecutor != null) {
			bExecutor.setColaborator(colaboratorFacade);
			return bExecutor.execute(request.getObjVO());
		}
		response = executeSecurity(request, mapsManager.getSecurityPrefixExecutors(request.getId()));
		if (response != null) {
			return response;
		}
		bExecutor = mapsManager.getBusinessPrefixExecutor(request.getId());
		if (bExecutor != null) {
			bExecutor.setColaborator(colaboratorFacade);
			return bExecutor.execute(request.getObjVO());
		}
		throw new NoExecutorFoundException("No executor found for request with id: " + request.getId());
	}

	private IRemoteResponse executeSecurity(RemoteRequest request, List<ISecurityExecutor> securityExecutorList) {
		if (securityExecutorList != null) {
			for (ISecurityExecutor sExecutor : securityExecutorList) {
				sExecutor.setColaborator(colaboratorFacade);
				MessageResponse r = sExecutor.execute(request.getObjVO());
				if (r != null) {
					return r;
				}
			}
		}
		return null;
	}

	@Override
	public IExecutorMapsManager getMapsManager() {
		return mapsManager;
	}

	@Override
	public void setMapsManager(IExecutorMapsManager mapsManager) {
		this.mapsManager = mapsManager;
	}

	@Override
	public CollaboratorFacade getColaboratorFacade() {
		return colaboratorFacade;
	}

	@Override
	public void setColaboratorFacade(CollaboratorFacade colaboratorFacade) {
		this.colaboratorFacade = colaboratorFacade;
	}
}
